import panzoom from 'panzoom'
import {tbType} from './tbType.js'

const coreMethods = {
  init() {
    this.jsPlumb.ready(() => {
      // 导入默认配置
      this.jsPlumb.importDefaults(this.jsPlumbSetting)
      this.loadFlow()
      this.initPanZoom()
      // 会使整个jsPlumb立即重绘。
      this.jsPlumb.setSuspendDrawing(false, true)
    })
  },
  // 加载
  loadFlow() {
    if (!this.json || !this.json.nodes || this.json.nodes.length === 0) {
      this.$message.error('json中nodes数组不能为空')
      return
    }
    if (!this.json || !this.json.nodes) {
      this.$message.error('json中edges数组不能是未定义')
      return
    }
    // 初始化节点
    this.json.nodes.forEach(node => {
      this.jsPlumb.draggable(node.id, {
        grid: this.commonGrid
      })
      const nodeType = node.type
      node.columns.forEach(col => {
        const colID = `${nodeType}${this.minus}${node.name}${this.minus}${col.name}`
        const props = {tbName: node.name, column: col.name}
        // 节点类型不同,添加端点的方向也不同.对于Origin/RS表来说 它们都只有一侧有端点.其他表都视为中间表两侧都有端点
        if (nodeType === tbType['Origin'].type) {
          this.addEndpoint(
            colID,
            ['Right'],
            {
              isSource: true
            },
            props
          )
        } else if (nodeType === tbType['RS'].type) {
          this.addEndpoint(
            colID,
            ['Left'],
            {
              isTarget: true
            },
            props
          )
        } else {
          this.addEndpoint(
            colID,
            ['Right', 'Left'],
            {
              isSource: true,
              isTarget: true
            },
            props
          )
        }
      })
    })

    // 初始化连线
    this.json.edges.forEach(edge => {
      let fromFull =
          tbType['Origin'].type +
          this.minus +
          edge.from.tbName +
          this.minus +
          edge.from.column +
          this.minus +
          'Right',
        toFull =
          tbType['RS'].type +
          this.minus +
          edge.to.tbName +
          this.minus +
          edge.to.column +
          this.minus +
          'Left'
      this.connect(fromFull, toFull)
    })

    // 绑定click点击连线的事件，记录当前选中的连线
    this.jsPlumb.bind('click', conn => {
      if (!conn) {
        return
      }
      if (this.currentConnect && this.currentConnect.id == conn.id) {
        this.currentConnect = null
      } else {
        this.currentConnect = conn
      }
    })
  },
  // 获取连线对应的数据
  getEdgeData() {
    const edges = []
    const connections = this.jsPlumb.getAllConnections()
    if (connections && connections.length > 0) {
      connections.forEach(conn => {
        const [source, target] = conn.endpoints
        const from = source.props
        const to = target.props
        edges.push({from, to})
      })
    }
    return edges
  },
  addEndpoint(elID, AnchorArr, setting, props) {
    //AnchorArr 可能有多个锚点需要添加
    AnchorArr.forEach(anchor => {
      const endpoint = this.jsPlumb.addEndpoint(
        elID,
        {
          anchors: anchor,
          uuid: elID + this.minus + anchor
        },
        Object.assign({}, this.jsPlumbSetting, setting)
      )
      endpoint.props = {...props}
    })
  },
  connect(from, to) {
    this.jsPlumb.connect(
      {
        uuids: [from, to]
      },
      this.jsPlumbSetting
    )
  },

  initPanZoom() {
    const mainContainer = this.jsPlumb.getContainer()
    const mainContainerWrap = mainContainer.parentNode
    const pan = panzoom(mainContainer, {
      smoothScroll: false,
      bounds: true,
      // autocenter: true,
      zoomDoubleClickSpeed: 1,
      minZoom: 0.5,
      maxZoom: 2,
      //设置滚动缩放的组合键，默认不需要组合键
      beforeWheel: e => {
        // console.log(e)
        // let shouldIgnore = !e.ctrlKey
        // return shouldIgnore
      },
      beforeMouseDown: function(e) {
        // allow mouse-down panning only if altKey is down. Otherwise - ignore
        const isSVG = e.target.className.constructor != String
        const shouldIgnore = e.ctrlKey
        return shouldIgnore || isSVG
      }
    })
    this.jsPlumb.mainContainerWrap = mainContainerWrap
    this.jsPlumb.pan = pan
    // 缩放时设置jsPlumb的缩放比率
    pan.on('zoom', e => {
      const {x, y, scale} = e.getTransform()
      this.jsPlumb.setZoom(scale)
    })
    pan.on('panend', e => {
      const {x, y, scale} = e.getTransform()
    })

    // 平移时设置鼠标样式
    mainContainerWrap.style.cursor = 'grab'
    mainContainerWrap.addEventListener('mousedown', function wrapMousedown() {
      this.style.cursor = 'grabbing'
      mainContainerWrap.addEventListener('mouseout', function wrapMouseout() {
        this.style.cursor = 'grab'
      })
    })
    mainContainerWrap.addEventListener('mouseup', function wrapMouseup() {
      this.style.cursor = 'grab'
    })
  },
  //初始化节点位置  （以便对齐,居中）
  fixNodesPosition() {
    if (this.json.nodes && this.$refs.flowWrap) {
      const nodeWidth = 120
      const nodeHeight = 40
      let wrapInfo = this.$refs.flowWrap.getBoundingClientRect()
      let maxLeft = 0,
        minLeft = wrapInfo.width,
        maxTop = 0,
        minTop = wrapInfo.height
      let nodePoint = {
        left: 0,
        right: 0,
        top: 0,
        bottom: 0
      }
      let fixTop = 0,
        fixLeft = 0
      this.json.nodes.forEach(el => {
        let top = el.top
        let left = el.left
        maxLeft = left > maxLeft ? left : maxLeft
        minLeft = left < minLeft ? left : minLeft
        maxTop = top > maxTop ? top : maxTop
        minTop = top < minTop ? top : minTop
      })
      nodePoint.left = minLeft
      nodePoint.right = wrapInfo.width - maxLeft - nodeWidth
      nodePoint.top = minTop
      nodePoint.bottom = wrapInfo.height - maxTop - nodeHeight

      fixTop =
        nodePoint.top !== nodePoint.bottom
          ? (nodePoint.bottom - nodePoint.top) / 4
          : 0
      fixLeft =
        nodePoint.left !== nodePoint.right
          ? (nodePoint.right - nodePoint.left) / 2
          : 0

      this.json.nodes.map(el => {
        let top = Number(el.top) + fixTop
        let left = Number(el.left) + fixLeft
        el.top = Math.round(top / 20) * 20
        el.left = Math.round(left / 20) * 20
      })
    }
  }
}

export default coreMethods
